home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / sc_22.zip / CC2.C < prev    next >
C/C++ Source or Header  |  1988-01-26  |  11KB  |  512 lines

  1. /*
  2. ** Small-C Compiler -- Part 2 -- Front End and Miscellaneous.
  3. ** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
  4. ** All rights reserved.
  5. */
  6.  
  7. #include <stdio.h>
  8. #include "cc.h"
  9.  
  10. extern char
  11.  *symtab, *macn, *macq, *pline, *mline,  optimize,
  12.   alarm, *glbptr, *line, *lptr, *cptr, *cptr2,  *cptr3,
  13.  *locptr, msname[NAMESIZE],  pause,  quote[2];
  14.  
  15. extern int
  16.   *wq,  ccode,  ch,  csp,  eof,  errflag,  iflevel,
  17.   input,  input2,  listfp,  macptr,  nch,
  18.   nxtlab,  op[16],  opindex,  opsize,  output,  pptr,
  19.   skiplevel,  *wqptr;
  20.  
  21. /********************** input functions **********************/
  22.  
  23. preprocess() {
  24.   int k;
  25.   char c;
  26.   if(ccode) {
  27.     line = mline;
  28.     ifline();
  29.     if(eof) return;
  30.     }
  31.   else {
  32.     inline();
  33.     return;
  34.     }
  35.   pptr = -1;
  36.   while(ch != NEWLINE && ch) {
  37.     if(white()) {
  38.       keepch(' ');
  39.       while(white()) gch();
  40.       }
  41.     else if(ch == '"') {
  42.       keepch(ch);
  43.       gch();
  44.       while(ch != '"' || (*(lptr-1) == 92 && *(lptr-2) != 92)) {
  45.         if(ch == NULL) {
  46.           error("no quote");
  47.           break;
  48.           }
  49.         keepch(gch());
  50.         }
  51.       gch();
  52.       keepch('"');
  53.       }
  54.     else if(ch == 39) {
  55.       keepch(39);
  56.       gch();
  57.       while(ch != 39 || (*(lptr-1) == 92 && *(lptr-2) != 92)) {
  58.         if(ch == NULL) {
  59.           error("no apostrophe");
  60.           break;
  61.           }
  62.         keepch(gch());
  63.         }
  64.       gch();
  65.       keepch(39);
  66.       }
  67.     else if(ch == '/' && nch == '*') {
  68.       bump(2);
  69.       while((ch == '*' && nch == '/') == 0) {
  70.         if(ch) bump(1);
  71.         else {
  72.           ifline();
  73.           if(eof) break;
  74.           }
  75.         }
  76.       bump(2);
  77.       }
  78.     else if(an(ch)) {
  79.       k = 0;
  80.       while(an(ch) && k < NAMEMAX) {
  81.         msname[k++] = ch;
  82.         gch();
  83.         }
  84.       msname[k] = NULL;
  85.       if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)) {
  86.         k = getint(cptr+NAMESIZE, 2);
  87.         while(c = macq[k++]) keepch(c);
  88.         while(an(ch)) gch();
  89.         }
  90.       else {
  91.         k = 0;
  92.         while(c = msname[k++]) keepch(c);
  93.         }
  94.       }
  95.     else keepch(gch());
  96.     }
  97.   if(pptr >= LINEMAX) error("line too long");
  98.   keepch(NULL);
  99.   line = pline;
  100.   bump(0);
  101.   }
  102.  
  103. keepch(c)  char c; {
  104.   if(pptr < LINEMAX) pline[++pptr] = c;
  105.   }
  106.  
  107. ifline() {
  108.   while(1) {
  109.     inline();
  110.     if(eof) return;
  111.     if(match("#ifdef")) {
  112.       ++iflevel;
  113.       if(skiplevel) continue;
  114.       symname(msname);
  115.       if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0) == 0)
  116.         skiplevel = iflevel;
  117.       continue;
  118.       }
  119.     if(match("#ifndef")) {
  120.       ++iflevel;
  121.       if(skiplevel) continue;
  122.       symname(msname);
  123.       if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0))
  124.         skiplevel = iflevel;
  125.       continue;
  126.       }
  127.     if(match("#else")) {
  128.       if(iflevel) {
  129.         if(skiplevel == iflevel) skiplevel = 0;
  130.         else if(skiplevel == 0)  skiplevel = iflevel;
  131.         }
  132.       else noiferr();
  133.       continue;
  134.       }
  135.     if(match("#endif")) {
  136.       if(iflevel) {
  137.         if(skiplevel == iflevel) skiplevel = 0;
  138.         --iflevel;
  139.         }
  140.       else noiferr();
  141.       continue;
  142.       }
  143.     if(skiplevel) continue;
  144.     if(ch == 0) continue;
  145.     break;
  146.     }
  147.   }
  148.  
  149. inline() {           /* numerous revisions */
  150.   int k, unit;
  151.   poll(1);           /* allow operator interruption */
  152.   if(input == EOF) openfile();
  153.   if(eof) return;
  154.   if((unit = input2) == EOF) unit = input;
  155.   if(fgets(line, LINEMAX, unit) == NULL) {
  156.     fclose(unit);
  157.     if(input2 != EOF)
  158.          input2 = EOF;
  159.     else input  = EOF;
  160.     *line = NULL;
  161.     }
  162.   else if(listfp) {
  163.     if(listfp == output) fputc(';', output);
  164.     fputs(line, listfp);
  165.     }
  166.   bump(0);
  167.   }
  168.  
  169. inbyte()  {
  170.   while(ch == 0) {
  171.     if(eof) return 0;
  172.     preprocess();
  173.     }
  174.   return gch();
  175.   }
  176.  
  177. /********************* scanning functions ********************/
  178.  
  179. /*
  180. ** test if next input string is legal symbol name
  181. */
  182. symname(sname) char *sname; {
  183.   int k;char c;
  184.   blanks();
  185.   if(alpha(ch) == 0) return (*sname = 0);
  186.   k = 0;
  187.   while(an(ch)) {
  188.     sname[k] = gch();
  189.     if(k < NAMEMAX) ++k;
  190.     }
  191.   sname[k] = 0;
  192.   return 1;
  193.   }
  194.  
  195. need(str)  char *str; {
  196.   if(match(str) == 0) error("missing token");
  197.   }
  198.  
  199. ns()  {
  200.   if(match(";") == 0) error("no semicolon");
  201.   else errflag = 0;
  202.   }
  203.  
  204. match(lit)  char *lit; {
  205.   int k;
  206.   blanks();
  207.   if(k = streq(lptr, lit)) {
  208.     bump(k);
  209.     return 1;
  210.     }
  211.   return 0;
  212.   }
  213.  
  214. streq(str1, str2)  char str1[], str2[]; {
  215.   int k;
  216.   k = 0;
  217.   while (str2[k]) {
  218.     if(str1[k] != str2[k]) return 0;
  219.     ++k;
  220.     }
  221.   return k;
  222.  }
  223.  
  224. amatch(lit, len)  char *lit; int len; {
  225.   int k;
  226.   blanks();
  227.   if(k = astreq(lptr, lit, len)) {
  228.     bump(k);
  229.     return 1;
  230.     }
  231.   return 0;
  232.  }
  233.  
  234. astreq(str1, str2, len)  char str1[], str2[]; int len; {
  235.   int k;
  236.   k = 0;
  237.   while (k < len) {
  238.     if(str1[k] != str2[k]) break;
  239.     /*
  240.     ** must detect end of symbol table names terminated by
  241.     ** symbol length in binary
  242.     */
  243.     if(str2[k] < ' ') break;
  244.     if(str1[k] < ' ') break;
  245.     ++k;
  246.     }
  247.   if(an(str1[k]) || an(str2[k])) return 0;
  248.   return k;
  249.   }
  250.  
  251. nextop(list) char *list; {
  252.   char op[4];
  253.   opindex = 0;
  254.   blanks();
  255.   while(1) {
  256.     opsize = 0;
  257.     while(*list > ' ') op[opsize++] = *list++;
  258.     op[opsize] = 0;
  259.     if(opsize = streq(lptr, op))
  260.       if(*(lptr+opsize) != '=' && 
  261.          *(lptr+opsize) != *(lptr+opsize-1))
  262.          return 1;
  263.     if(*list) {
  264.       ++list;
  265.       ++opindex;
  266.       }
  267.     else return 0;
  268.     }
  269.   }
  270.  
  271. blanks() {
  272.   while(1) {
  273.     while(ch) {
  274.       if(white()) gch();
  275.       else return;
  276.       }
  277.     if(line == mline) return;
  278.     preprocess();
  279.     if(eof) break;
  280.     }
  281.   }
  282.  
  283. white() {
  284.   avail(YES);  /* abort on stack/symbol table overflow */
  285.   return (*lptr <= ' ' && *lptr);
  286.   }
  287.  
  288. gch() {
  289.   int c;
  290.   if(c = ch) bump(1);
  291.   return c;
  292.   }
  293.  
  294. bump(n) int n; {
  295.   if(n) lptr += n;
  296.   else  lptr  = line;
  297.   if(ch = nch = *lptr) nch = *(lptr+1);
  298.   }
  299.  
  300. kill() {
  301.   *line = 0;
  302.   bump(0);
  303.   }
  304.  
  305. skip() {
  306.   if(an(inbyte()))
  307.        while(an(ch)) gch();
  308.   else while(an(ch) == 0) {
  309.     if(ch == 0) break;
  310.     gch();
  311.     }
  312.   blanks();
  313.   }
  314.  
  315. endst() {
  316.   blanks();
  317.   return (streq(lptr, ";") || ch == 0);
  318.   }
  319.  
  320. /*********** symbol table management functions ***********/
  321.  
  322. addsym(sname, id, type, size, value, lgpp, class)
  323.   char *sname, id, type;  int size, value, *lgpp, class; {
  324.   if(lgpp == &glbptr) {
  325.     if(cptr2 = findglb(sname)) return cptr2;
  326.     if(cptr == 0) {
  327.       error("global symbol table overflow");
  328.       return 0;
  329.       }
  330.     }
  331.   else {
  332.     if(locptr > (ENDLOC-SYMMAX)) {
  333.       error("local symbol table overflow");
  334.       abort(ERRCODE);
  335.       }
  336.     cptr = *lgpp;
  337.     }
  338.   cptr[IDENT] = id;
  339.   cptr[TYPE]  = type;
  340.   cptr[CLASS] = class;
  341.   putint(size, cptr + SIZE, 2);
  342.   putint(value, cptr + OFFSET, 2);
  343.   cptr3 = cptr2 = cptr + NAME;
  344.   while(an(*sname)) *cptr2++ = *sname++;
  345.   if(lgpp == &locptr) {
  346.     *cptr2 = cptr2 - cptr3;         /* set length */
  347.     *lgpp = ++cptr2;
  348.     }
  349.   return cptr;
  350.   }
  351.  
  352. /*
  353. ** search for symbol match
  354. ** on return cptr points to slot found or empty slot
  355. */
  356. search(sname, buf, len, end, max, off)
  357.   char *sname, *buf, *end;  int len, max, off; {
  358.   cptr  =
  359.   cptr2 = buf+((hash(sname)%(max-1))*len);
  360.   while(*cptr != NULL) {
  361.     if(astreq(sname, cptr+off, NAMEMAX)) return 1;
  362.     if((cptr = cptr+len) >= end) cptr = buf;
  363.     if(cptr == cptr2) return (cptr = 0);
  364.     }
  365.   return 0;
  366.   }
  367.  
  368. hash(sname) char *sname; {
  369.   int i, c;
  370.   i = 0;
  371.   while(c = *sname++) i = (i << 1) + c;
  372.   return i;
  373.   }
  374.  
  375. findglb(sname)  char *sname; {
  376.   if(search(sname, STARTGLB, SYMMAX, ENDGLB, NUMGLBS, NAME))
  377.     return cptr;
  378.   return 0;
  379.   }
  380.  
  381. findloc(sname)  char *sname;  {
  382.   cptr = locptr - 1;  /* search backward for block locals */
  383.   while(cptr > STARTLOC) {
  384.     cptr = cptr - *cptr;
  385.     if(astreq(sname, cptr, NAMEMAX)) return (cptr - NAME);
  386.     cptr = cptr - NAME - 1;
  387.     }
  388.   return 0;
  389.   }
  390.  
  391. nextsym(entry) char *entry; {
  392.   entry = entry + NAME;
  393.   while(*entry++ >= ' ');    /* find length byte */
  394.   return entry;
  395.   }
  396.  
  397. /******** while queue management functions *********/  
  398.  
  399. addwhile(ptr)  int ptr[]; {
  400.   int k;
  401.   ptr[WQSP]   = csp;         /* and stk ptr */
  402.   ptr[WQLOOP] = getlabel();  /* and looping label */
  403.   ptr[WQEXIT] = getlabel();  /* and exit label */
  404.   if(wqptr == WQMAX) {
  405.     error("control statement nesting limit");
  406.     abort(ERRCODE);
  407.     }
  408.   k = 0;
  409.   while (k < WQSIZ) *wqptr++ = ptr[k++];
  410.   }
  411.  
  412. readwhile(ptr) int *ptr; {
  413.   if(ptr <= wq) {
  414.     error("out of context");
  415.     return 0;
  416.     }
  417.   else return (ptr - WQSIZ);
  418.  }
  419.  
  420. delwhile() {
  421.   if(wqptr > wq) wqptr -= WQSIZ;
  422.   }
  423.  
  424. /****************** utility functions ********************/  
  425.  
  426. /*
  427. ** test if c is alphabetic
  428. */
  429. alpha(c)  char c; {
  430.   return (isalpha(c) || c == '_');
  431.   }
  432.  
  433. /*
  434. ** test if given character is alphanumeric
  435. */
  436. an(c)  char c; {
  437.   return (alpha(c) || isdigit(c));
  438.   }
  439.  
  440. /*
  441. ** return next avail internal label number
  442. */
  443. getlabel() {
  444.   return(++nxtlab);
  445.   }
  446.  
  447. /*
  448. ** get integer of length len from address addr
  449. ** (byte sequence set by "putint")
  450. */
  451. getint(addr, len) char *addr; int len; {
  452.   int i;
  453.   i = *(addr + --len);  /* high order byte sign extended */
  454.   while(len--) i = (i << 8) | *(addr + len) & 255;
  455.   return i;
  456.   }
  457.  
  458. /*
  459. ** put integer i of length len into address addr
  460. ** (low byte first)
  461. */
  462. putint(i, addr, len) char *addr; int i, len; {
  463.   while(len--) {
  464.     *addr++ = i;
  465.     i = i >> 8;
  466.     }
  467.   }
  468.  
  469. lout(line, fd) char *line; int fd; {
  470.   fputs(line, fd);
  471.   fputc(NEWLINE, fd);
  472.   }
  473.  
  474. /******************* error functions *********************/  
  475.  
  476. illname() {
  477.   error("illegal symbol");
  478.   skip();
  479.   }
  480.  
  481. multidef(sname)  char *sname; {
  482.   error("already defined");
  483.   }
  484.  
  485. needlval() {
  486.   error("must be lvalue");
  487.   }
  488.  
  489. noiferr() {
  490.   error("no matching #if...");
  491.   errflag = 0;
  492.   }
  493.  
  494. error(msg) char msg[]; {
  495.   if(errflag) return;
  496.   else errflag = 1;
  497.   lout(line, stderr);
  498.   errout(msg, stderr);
  499.   if(alarm) fputc(7, stderr);
  500.   if(pause) while(fgetc(stderr) != NEWLINE);
  501.   if(listfp > 0) errout(msg, listfp);
  502.   }
  503.  
  504. errout(msg, fp) char msg[]; int fp; {
  505.   int k;
  506.   k = line+2;
  507.   while(k++ <= lptr) fputc(' ', fp);
  508.   lout("/\\", fp);
  509.   fputs("**** ", fp); lout(msg, fp);
  510.   }
  511.  
  512.